import re

from rest_framework_mongoengine.serializers import DocumentSerializer, serializers
from django.conf import settings

from models.strategy import CustomProfileTemplate, SystemProfileTemplate
from models.kb import KbVuln
from apps.strategy.display import Tips
from utilities.regex import NAME_RE
from wass.display import LANGUAGE_CODE
from utilities.djconsole import djconsole


class CustomProfileTemplateSerializer(DocumentSerializer):
    max_count = -1

    def __init__(self, *args, **kwargs):
        self.license_info = djconsole.get_license_detail(kwargs.get('context', {}).get('request'))
        self.set_max_count(int(self.license_info.get('max_vul_template_number', settings.DEFAULT_VUL_TEMPLATE_NUMBER)))
        super(CustomProfileTemplateSerializer, self).__init__(*args, **kwargs)

    class Meta:
        model = CustomProfileTemplate
        fields = [
            'custom_profile_template_id',
            'name',
            'description',
            'plugin_list',
            'created_at',
            'updated_at',
            'display_name'
        ]

    custom_profile_template_id = serializers.CharField(default="", read_only=True)
    name = serializers.CharField(max_length=16, required=False)
    description = serializers.CharField(
        max_length=Meta.model.description.max_length, default='', required=False, allow_blank=True)
    plugin_list = serializers.ListField(max_length=16384, default=[], allow_empty=False)
    created_at = serializers.DateTimeField(read_only=True)
    updated_at = serializers.DateTimeField(read_only=True)
    display_name = serializers.DictField(default={}, required=False)

    def validate_name(self, name):
        tips = Tips()
        if not re.match(NAME_RE, name):
            raise serializers.ValidationError(tips.get(0))

        query = {'name': name}
        if self.instance:
            query['custom_profile_template_id'] = {'$ne': self.instance.custom_profile_template_id}
        if self.Meta.model.objects.find_one(query):
            raise serializers.ValidationError(tips.get(1, (name, )))
        return name

    def validate_display_name(self, display_name):
        display_name.setdefault(LANGUAGE_CODE, self.initial_data.get('name'))

        return display_name

    @staticmethod
    def validate_plugin_list(plugin_list):
        plugin_list = list({item.key for item in KbVuln.objects.filter(key__in=plugin_list)})
        if not plugin_list:
            raise serializers.ValidationError(Tips().get(3))
        return plugin_list

    def create(self, validated_data):
        max_count = self.max_count
        setattr(self, 'max_vul_template_number', max_count)
        if self.Meta.model.objects.count() >= max_count:
            raise serializers.ValidationError(Tips().get(2, (max_count, )))

        data = {**validated_data, 'custom_id': self.initial_data.get('custom_id', '')}
        return self.Meta.model(**data).save()

    @staticmethod
    def get_plugin_list_statistics(plugin_list, plugin_dict):
        statistics = {
            "plugin_types": {},
            "plugin_severity": {},
            'plugins_count': len(plugin_list)
        }
        for key in plugin_list:
            item = plugin_dict.get(key)
            if not item:
                continue
            name = item.get('name', {}).get(LANGUAGE_CODE, 'unknown')
            severity = item.get('severity', 0)
            for vuln_type in item.get('vuln_type', []):
                statistics['plugin_types'].setdefault(vuln_type.get(LANGUAGE_CODE, 'unknown'), []).append(name)
            statistics['plugin_severity'][severity] = statistics['plugin_severity'].get(severity, 0) + 1

        return statistics

    @classmethod
    def set_max_count(cls, max_count: int):
        cls.max_count = max_count


class SystemProfileTemplateSerializer(DocumentSerializer):
    class Meta:
        model = SystemProfileTemplate
        fields = [
            'name',
            'value',
            'description',
            'plugin_list',
            'created_at',
            'updated_at',
            'display_name',
            'is_disabled'
        ]

    name = serializers.CharField(read_only=True)
    display_name = serializers.DictField(read_only=True)
    value = serializers.IntegerField(read_only=True)
    description = serializers.CharField(read_only=True)
    plugin_list = serializers.CharField(read_only=True)
    created_at = serializers.DateTimeField(read_only=True)
    updated_at = serializers.DateTimeField(read_only=True)
    is_disabled = serializers.BooleanField(default=False)


class SystemProfileTemplateSearchSerializer(DocumentSerializer):
    class Meta:
        model = SystemProfileTemplate
        fields = [
            'template_id',
            'description',
            'display_name',
            'is_disabled'
        ]

    template_id = serializers.IntegerField(source="value", read_only=True)
    description = serializers.CharField(read_only=True)
    display_name = serializers.DictField(read_only=True)
    is_disabled = serializers.BooleanField(default=False)


class CustomProfileTemplateSearchSerializer(DocumentSerializer):
    class Meta:
        model = CustomProfileTemplate
        fields = [
            'template_id',
            'description',
            'display_name'
        ]

    template_id = serializers.CharField(source='custom_profile_template_id', read_only=True)
    description = serializers.CharField(read_only=True)
    display_name = serializers.DictField(read_only=True, default={})
